home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
program
/
progem.lzh
/
apndx10.prf
< prev
next >
Wrap
Text File
|
1987-06-23
|
15KB
|
568 lines
.!****************************************************************************
.!
.! ANTIC PUBLISHING INC., COPYRIGHT 1985. REPRINTED BY PERMISSION.
.!
.! ** Professional GEM ** by Tim Oren
.!
.! Proff File by ST enthusiasts at
.! Case Western Reserve University
.! Cleveland, Ohio
.! uucp : decvax!cwruecmp!bammi
.! csnet: bammi@case
.! arpa : bammi%case@csnet-relay
.! compuserve: 71515,155
.!
.!****************************************************************************
.!
.! Begin Appendix 10
.!
.!***************************************************************************
.!
.!
.AP X Sample Code for Part XIII
#include "portab.h" /* portable coding conv */
#include "machine.h" /* machine depndnt conv */
#include "obdefs.h" /* object definitions */
#include "gembind.h" /* gem binding structs */
#include "taddr.h"
#define M1_ENTER 0x0000
#define M1_EXIT 0x0001
#define BS 0x0008
#define TAB 0x0009
#define CR 0x000D
#define ESC 0x001B
#define BTAB 0x0f00
#define UP 0x4800
#define DOWN 0x5000
#define DEL 0x5300
/* Global variables used by */
/* 'mapped' functions */
MLOCAL GRECT br_rect; /* Current break rectangle */
MLOCAL WORD br_mx, br_my, br_togl; /* Break mouse posn & flag */
MLOCAL WORD fn_obj; /* Found tabable object */
MLOCAL WORD fn_last; /* Object tabbing from */
MLOCAL WORD fn_prev; /* Last EDITABLE obj seen */
MLOCAL WORD fn_dir; /* 1 = TAB, 0 = BACKTAB */
/************* Utility routines for new forms manager ***************/
VOID
objc_toggle(tree, obj) /* Reverse the SELECT state */
LONG tree; /* of an object, and redraw */
WORD obj; /* it immediately. */
{
WORD state, newstate;
GRECT root, ob_rect;
objc_xywh(tree, ROOT, &root);
state = LWGET(OB_STATE(obj));
newstate = state ^ SELECTED;
objc_change(tree, obj, 0, root.g_x, root.g_y,
root.g_w, root.g_h, newstate, 1);
}
.bp
VOID /* If the object is not already */
objc_sel(tree, obj) /* SELECTED, make it so. */
LONG tree;
WORD obj;
{
if ( !(LWGET(OB_STATE(obj)) & SELECTED) )
objc_toggle(tree, obj);
}
VOID /* If the object is SELECTED, */
objc_dsel(tree, obj) /* deselect it. */
LONG tree;
WORD obj;
{
if (LWGET(OB_STATE(obj)) & SELECTED)
objc_toggle(tree, obj);
}
VOID /* Return the object's GRECT */
objc_xywh(tree, obj, p) /* through 'p' */
LONG tree;
WORD obj;
GRECT *p;
{
objc_offset(tree, obj, &p->g_x, &p->g_y);
p->g_w = LWGET(OB_WIDTH(obj));
p->g_h = LWGET(OB_HEIGHT(obj));
}
.bp
VOID /* Non-cursive traverse of an */
map_tree(tree, this, last, routine) /* object tree. This routine */
LONG tree; /* is described in PRO GEM #5. */
WORD this, last;
WORD (*routine)();
{
WORD tmp1;
tmp1 = this; /* Initialize to impossible value: */
/* TAIL won't point to self! */
/* Look until final node, or off */
/* the end of tree */
while (this != last && this != NIL)
/* Did we 'pop' into this node */
/* for the second time? */
if (LWGET(OB_TAIL(this)) != tmp1)
{
tmp1 = this; /* This is a new node */
this = NIL;
/* Apply operation, testing */
/* for rejection of sub-tree */
if ((*routine)(tree, tmp1))
this = LWGET(OB_HEAD(tmp1));
/* Subtree path not taken, */
/* so traverse right */
if (this == NIL)
this = LWGET(OB_NEXT(tmp1));
}
else /* Revisiting parent: */
/* No operation, move right */
{
tmp1 = this;
this = LWGET(OB_NEXT(tmp1));
}
}
.bp
WORD /* Find the parent object of */
get_parent(tree, obj) /* by traversing right until */
LONG tree; /* we find nodes whose NEXT */
WORD obj; /* and TAIL links point to */
{ /* each other. */
WORD pobj;
if (obj == NIL)
return (NIL);
pobj = LWGET(OB_NEXT(obj));
if (pobj != NIL)
{
while( LWGET(OB_TAIL(pobj)) != obj )
{
obj = pobj;
pobj = LWGET(OB_NEXT(obj));
}
}
return(pobj);
}
WORD
inside(x, y, pt) /* determine if x,y is in rectangle */
WORD x, y;
GRECT *pt;
{
if ( (x >= pt->g_x) && (y >= pt->g_y) &&
(x < pt->g_x + pt->g_w) && (y < pt->g_y + pt->g_h) )
return(TRUE);
else
return(FALSE);
}
WORD
rc_intersect(p1, p2) /* compute intersection of two GRECTs */
GRECT *p1, *p2;
{
WORD tx, ty, tw, th;
tw = min(p2->g_x + p2->g_w, p1->g_x + p1->g_w);
th = min(p2->g_y + p2->g_h, p1->g_y + p1->g_h);
tx = max(p2->g_x, p1->g_x);
ty = max(p2->g_y, p1->g_y);
p2->g_x = tx;
p2->g_y = ty;
p2->g_w = tw - tx;
p2->g_h = th - ty;
return( (tw > tx) && (th > ty) );
}
.bp
VOID
rc_copy(psbox, pdbox) /* copy source to destination rectangle */
GRECT *psbox;
GRECT *pdbox;
{
pdbox->g_x = psbox->g_x;
pdbox->g_y = psbox->g_y;
pdbox->g_w = psbox->g_w;
pdbox->g_h = psbox->g_h;
}
/************* "Hot-spot" manager and subroutines ***************/
WORD
break_x(pxy)
WORD *pxy;
{ /* Breaking object is right of */
if (br_mx < pxy[0]) /* mouse. Reduce width of */
{ /* bounding rectangle. */
br_rect.g_w = pxy[0] - br_rect.g_x;
return (TRUE);
}
if (br_mx > pxy[2]) /* Object to left. Reduce width*/
{ /* and move rect. to right */
br_rect.g_w += br_rect.g_x - pxy[2] - 1;
br_rect.g_x = pxy[2] + 1;
return (TRUE);
}
return (FALSE); /* Mouse within object segment. */
} /* Break attempt fails. */
.bp
WORD
break_y(pxy)
WORD *pxy;
{
if (br_my < pxy[1]) /* Object below mouse. Reduce */
{ /* height of bounding rect. */
br_rect.g_h = pxy[1] - br_rect.g_y;
return (TRUE);
}
if (br_my > pxy[3]) /* Object above mouse. Reduce */
{ /* height and shift downward. */
br_rect.g_h += br_rect.g_y - pxy[3] - 1;
br_rect.g_y = pxy[3] + 1;
return (TRUE);
}
/* Emergency escape test! Protection vs. turkeys who nest */
/* non-selectable objects inside of selectables. */
if (br_mx >= pxy[0] && br_mx <= pxy[1])
{ /* Will X break fail? */
br_rect.g_x = br_mx; /* If so, punt! */
br_rect.g_y = br_my;
br_rect.g_w = br_rect.g_h = 1;
return (TRUE);
}
return (FALSE);
}
.bp
WORD
break_obj(tree, obj) /* Called once per object to */
LONG tree; /* check if the bounding rect. */
WORD obj; /* needs to be modified. */
{
GRECT s;
WORD flags, broken, pxy[4];
objc_xywh(tree, obj, &s);
grect_to_array(&s, pxy);
if (!rc_intersect(&br_rect, &s))
return (FALSE); /* Trivial rejection case */
flags = LWGET(OB_FLAGS(obj)); /* Is this object a potential */
if (flags & HIDETREE) /* hot-spot? */
return (FALSE);
if ( !(flags & SELECTABLE) )
return (TRUE);
if (LWGET(OB_STATE(obj)) & DISABLED)
return (TRUE);
for (broken = FALSE; !broken; ) /* This could take two passes */
{ /* if the first break fails. */
if (br_togl)
broken = break_x(pxy);
else
broken = break_y(pxy);
br_togl = !br_togl;
}
return (TRUE);
}
.bp
WORD /* Manages mouse rectangle events */
form_hot(tree, hot_obj, mx, my, rect, mode)
LONG tree;
WORD hot_obj, mx, my, *mode;
GRECT *rect;
{
GRECT root;
WORD state;
objc_xywh(tree, ROOT, &root); /* If there is already a hot-spot */
if (hot_obj != NIL) /* turn it off. */
objc_toggle(tree, hot_obj);
if (!(inside(mx, my, &root)) ) /* Mouse has moved outside of */
{ /* the dialog. Wait for return. */
*mode = M1_ENTER;
rc_copy(&root, rect);
return (NIL);
}
/* What object is mouse over? */
/* (Hit is guaranteed.) */
hot_obj = objc_find(tree, ROOT, MAX_DEPTH, mx, my);
/* Is this object a hot-spot? */
state = LWGET(OB_STATE(hot_obj));
if (LWGET(OB_FLAGS(hot_obj)) & SELECTABLE)
if ( !(state & DISABLED) )
{ /* Yes! Set up wait state. */
*mode = M1_EXIT;
objc_xywh(tree, hot_obj, rect);
if (state & SELECTED) /* But only toggle if it's not */
return (NIL); /* already SELECTED! */
else
{
objc_toggle(tree, hot_obj);
return (hot_obj);
}
}
rc_copy(&root, &br_rect); /* No hot object, so compute */
br_mx = mx; /* mouse bounding rectangle. */
br_my = my;
br_togl = 0;
map_tree(tree, ROOT, NIL, break_obj);
rc_copy(&br_rect, rect); /* Then return to wait state. */
*mode = M1_EXIT;
return (NIL);
}
.bp
/************* Key